gusucode.com > VC++ RingSDK界面库 > VC++ RingSDK界面库/code/example/tutorial/05_iseebrowser/viewer.cpp

    /**********************************************************************
//
//
//        ##########                          ######  #########   # ######    #
//      #############                      ########### ######### #########  ###
//     ######## # ###  ##                 ############# ##    ## #####  # ####
//     ####  ##    ## ###                 ###     ### # #      #####   #####
//          #     ###  #            #     ##       ##  ##      ##     ###
//         ## ###### ##      ##  ####    ####          #       #     ##
//       #########  ###  ## ### #######   ######      ##      ##    ###
//      ######      ##  ######  ##  ##       ####     #      ##     ####
//     #######     ##   ###### ##  ###          ##   ##     ###    ######
//     #########   ##  ###### ## ######         ### ##    ###      #  #####
//    ##    ###### ####### ### #### ##  ## #######  ########      ##    ####
//    ##      #### ###  #  ### ### ##  ##########   ######       ##      ####
//   ##         ##                ##   #########    ####         #         ##
//               #              ###
//                              ##
//                             ###
//                             ##
//
//
//							RingSDK 演示程序(ISee图象浏览器)
//作者:临风
//
//版本:1.0
//
//声明:本类库可以自由使用而不须对作者作出任何回报,但作者希望能得到
//		  你的鼓励和支持。你可以对类库源码作出修改和改进,但希望你能在
//		  修改的同时给作者一份同样的副本。
//		  本类库不得用于任何商业用途,如确实需要,请与作者联系。
//
//e-mail:ringphone@sina.com
//
//说明:MDI子窗口,图象显示部分代码
//
**********************************************************************/
#include "global.h"

//放大/缩小倍数设置
int gZoomOut[14] = {0,2,3,4,6,8,12,16,20,25,33,50,66,100};
int gZoomIn[10] = {1,2,3,4,5,6,7,8,12,16};

BEGIN_REGMSG(child)
	REGMSG(WM_PAINT)
	REGMSG(WM_ERASEBKGND)
	REGMSG(WM_SIZE)
	REGMSG(WM_LBUTTONDOWN)
	REGMSG(WM_MOUSEMOVE)
	REGMSG(WM_LBUTTONUP)
	REGMSG(WM_LBUTTONDBLCLK)
	REGMSG(WM_KEYDOWN)
	REGMSG(WM_INITDIALOG)
END_REGMSG

void RINGMETHOD(child,SetCursor)(HCURSOR hCur)
{
	m_hCursor = hCur;
	RingBaseWnd::SetCursor(hCur);
}

RINGMSG(child,WM_INITDIALOG)
{
	m_bFullScreen = FALSE;
	m_nRadio = 0;
	SetRectEmpty(&m_rcFloat);
	//设置m_dib的绘制目标为本窗口
	m_dib.SetTarget(m_hWnd);
	
	//设置窗口类光标为NULL,如不设置,则设置其他光标,鼠标一移动就会恢复为原始光标.
	SetCursor(NULL);
	m_hCurHand = LoadCursor(GetInstance(),MAKEINTRESOURCE(IDC_MOVEHAND));
	m_hCurGrab = LoadCursor(GetInstance(),MAKEINTRESOURCE(IDC_GRAB));
	m_hCurZoom = LoadCursor(GetInstance(),MAKEINTRESOURCE(IDC_ZOOMGLASS));
	m_hCurArr = LoadCursor(NULL,IDC_ARROW);
	m_hCursor = m_hCurArr;
	SetCursor(m_hCurArr);
	return FALSE;
}

RINGMSG(child,WM_SIZE)
{
	//尺寸变动,重新计算图象缩放倍率
	UpdatePicShow();
	InvalidateRect(m_hWnd,NULL,FALSE);
	return FALSE;
}

RINGMSG(child,WM_ERASEBKGND)
{
	return TRUE;
}

RINGMSG(child,WM_PAINT)
{
	RECT rc,rcImage;
	PAINTSTRUCT ps;
	
	GetClientRect(&rc);
	m_dib.GetDestRect(&rcImage);
	//绘制图象
	BeginPaint(m_hWnd,&ps);
	m_dib.Draw(ps.hdc);
	//排除图象区域绘制背景,这样不会产生闪烁
	ExcludeClipRect(ps.hdc,rcImage.left,rcImage.top,rcImage.right,rcImage.bottom);
	//绘制背景
	FillRect(ps.hdc,&rc,(HBRUSH)GetStockObject(BLACK_BRUSH));
	EndPaint(m_hWnd,&ps);
	return 0;
}

RINGMSG(child,WM_KEYDOWN)
{
	if(param.wParam == VK_RETURN || param.wParam == VK_ESCAPE)
	{
		SetFullScreen(!m_bFullScreen);
		NavPane->m_fileview->SetFocus();
	}
	else if(m_bFullScreen)
	{
		//全屏状态下按键处理
		switch(param.wParam)
		{
			case VK_NEXT:
				ViewNextImg();
				break;
			case VK_PRIOR:
				ViewNextImg(FALSE);
				break;
			case VK_ADD:
				//放大
				ZoomIn();
				break;
			case VK_SUBTRACT:
				//缩小
				ZoomOut();
				break;
			case VK_UP:
			case VK_DOWN:
			case VK_LEFT:
			case VK_RIGHT:
				MoveImg(param.wParam);
				InvalidateRect(m_hWnd,NULL,FALSE);
				break;
		}
	}
	return 0;
}

RINGMSG(child,WM_LBUTTONDOWN)
{
	SetCapture(m_hWnd);
	
	if(m_hCursor == m_hCurHand)
		SetCursor(m_hCurGrab);
	
	m_ptMouse.x = param.mousept.x;
	m_ptMouse.y = param.mousept.y;
	return DefaultProc(param);
}

RINGMSG(child,WM_MOUSEMOVE)
{
	if(m_hCursor == m_hCurGrab)
	{
		MoveImg(param.mousept.x - m_ptMouse.x,param.mousept.y - m_ptMouse.y);
		m_ptMouse.x = param.mousept.x;
		m_ptMouse.y = param.mousept.y;
	}
	return DefaultProc(param);
}

RINGMSG(child,WM_LBUTTONUP)
{
	ReleaseCapture();
	if(m_hCursor == m_hCurGrab)
		SetCursor(m_hCurHand);
	return DefaultProc(param);
}

RINGMSG(child,WM_LBUTTONDBLCLK)
{
	SetFullScreen(!m_bFullScreen);
	return 0;
}

void RINGMETHOD(child,ZoomIn)()
{
	if(m_nRadio == VIEW_FITSIZE)
		m_nRadio = CalcRadio();
	m_nRadio ++;
	if(m_nRadio > 9)
		m_nRadio = 9;
	SetImgDest();
	InvalidateRect(m_hWnd,NULL,FALSE);
}

void RINGMETHOD(child,ZoomOut)()
{
	if(m_nRadio == VIEW_FITSIZE)
		m_nRadio = CalcRadio();
	m_nRadio --;
	if(m_nRadio < 0)
	{
		SIZE dest = {m_dib.Width(),m_dib.Height()};
		int nStep = 1,nRadio = -m_nRadio - 1;
		while(nRadio > 13)
		{
			nRadio -= 14;
			nStep *= 100; 
		}
		if(nRadio == 0)
		{
			//66.7%
			dest.cx = (dest.cx*2)/3;
			dest.cy = (dest.cy*2)/3;
		}
		else
		{
			dest.cx /= gZoomOut[nRadio];
			dest.cy /= gZoomOut[nRadio];			
		}
		dest.cx /= nStep;
		dest.cy /= nStep;
		
		if(dest.cx < 10 || dest.cy < 10)
			m_nRadio ++;
	}
	SetImgDest();
	InvalidateRect(m_hWnd,NULL,FALSE);
}

void RINGMETHOD(child,ViewNextImg)(BOOL bNext)
{
	//上/下一幅图象
	int nIndex = window->m_fileview->GetCurSel();
	char szFile[MAX_PATH];

	if(bNext)
		nIndex ++;
	else
		nIndex --;

	while(nIndex >= 0 && nIndex < window->m_fileview->GetCount())
	{
		wsprintf(szFile,"%s\\%s",window->m_dirtree->GetSelFolderName(),
					window->m_fileview->RingListView::GetText(nIndex,0));
		if(m_dib.IsImage(szFile))
		{
			window->m_fileview->Select(nIndex);
			break;
		}
		if(bNext)
			nIndex ++;
		else
			nIndex --;
	}
}

//////////////////////////////////////////////////////////
//
//全屏模式切换,同样是停靠窗口的非典型用法,要求在浮动状态
//下全屏显示,只能更改浮动容器的窗口类型,这种情况很少见,
//因此这里不推荐这种做法,当然一般也用不着。
//
//////////////////////////////////////////////////////////
void RINGMETHOD(child,SetFullScreen)(BOOL bFullScreen)
{
	if(bFullScreen != m_bFullScreen)
	{
		RingBaseWnd* p;
		//状态改变
		if(bFullScreen)
		{
			RECT rc = {0,0,WINVAR_DESKTOP_X,WINVAR_DESKTOP_Y};
			//设置为浮动
			if(!IsFloat(GetDockState()))
				DockBack();
			//全屏处理
			p = GetWindowPtr(GetParent());
			if(p)
			{
				p->ReplaceStyle(WS_CAPTION | WS_THICKFRAME,0);
				//保存原窗口位置
				GetWindowRect(p->Handle(),&m_rcFloat);
				p->SetPos(0,0,WINVAR_DESKTOP_X,WINVAR_DESKTOP_Y);
			}
		}
		else
		{
			p = GetWindowPtr(GetParent());
			if(p)
			{
				p->ReplaceStyle(0,WS_CAPTION | WS_THICKFRAME);
			}
			DockBack();
			if(GetParent() == NavPane->GetDockSite(0)->Handle())
			{
				RECT rc;
				GetWindowRect(NavPane->m_navtool->Handle(),&rc);
				OffsetRect(&rc,-rc.left,Height());
				NavPane->m_navtool->DockTo(TBS_FLAG_DOCKTOP,&rc);
			}
		}
		m_bFullScreen = bFullScreen;
		m_nRadio = VIEW_FITSIZE;
		UpdatePicShow();
		InvalidateRect(m_hWnd,NULL,FALSE);
	}
}

BOOL RINGMETHOD(child,View)(LPCTSTR lpszPic)
{
	BOOL bOK = m_dib.Load((LPSTR)lpszPic);
	if(bOK)
	{
		m_dib.EnableAniGif();
		m_nRadio = VIEW_FITSIZE;
		UpdatePicShow();
		char szInfo[40],szFormat[8];
		wsprintf(szInfo,"%dx%d %s",m_dib.Width(),m_dib.Height(),m_dib.GetFormat(szFormat));
		window->m_statbar->SetValue(szInfo,3);
	}
	else
	{
		//m_dib载入图象失败,有可能仍保持原图象,设置绘制目标矩形为空(设宽高为负数)
		m_dib.SetDest(0,0,-1,-1);
		window->m_statbar->SetValue("",3);
	}
	InvalidateRect(m_hWnd,NULL,FALSE);
	return bOK;
}

void RINGMETHOD(child,UpdatePicShow)()
{
	RECT rc;
	SIZE dest;
	
	dest.cx = m_dib.Width();
	dest.cy = m_dib.Height();
	GetClientRect(&rc);
	
	//计算图象显示宽高
	if(rc.right < dest.cx)
	{
		//拉伸显示
		dest.cy = rc.right*m_dib.Height()/m_dib.Width();
		if(dest.cy > rc.bottom)
		{
			dest.cy = rc.bottom;
			dest.cx = dest.cy*m_dib.Width()/m_dib.Height();
		}
		else
			dest.cx = rc.right;
	}
	else if(rc.bottom < dest.cy)
	{
		//拉伸显示
		dest.cx = rc.bottom*m_dib.Width()/m_dib.Height();
		if(dest.cx > rc.right)
		{
			dest.cx = rc.right;
			dest.cy = dest.cx*m_dib.Height()/m_dib.Width();
		}
		else
			dest.cy = rc.bottom;
	}		
	
	//设置目标位置(注意:动画GIF必须,否则采用默认(0,0)位置,不会居中)
	m_dib.SetDest((rc.right - dest.cx)/2,(rc.bottom - dest.cy)/2,dest.cx,dest.cy);	
}

int RINGMETHOD(child,CalcRadio)()
{
	RECT rc;
	SIZE src;
	
	src.cx = m_dib.Width();
	src.cy = m_dib.Height();
	m_dib.GetDestRect(&rc);
	
	//计算图象显示比率
	int xRadio = src.cx/(rc.right - rc.left);
	int yRadio = src.cy/(rc.bottom - rc.top);
	int nradio,nCnt=0;
	if((xRadio >= 1 || yRadio >= 1) && 
		(src.cx%(rc.right - rc.left) > 0 || src.cy%(rc.bottom - rc.top) > 0))
	{
		//已缩小显示,计算比率
		if(xRadio == 1)
			return -1;	 //66.7%

		nradio = xRadio;
		while(nradio > 100)
		{
			nradio /= 100;
			nCnt ++;
		}
		int nAbs,nMin = 100000;
		for(int i=1;i<14;i++)
		{
			nAbs = abs(nradio - gZoomOut[i]);
			if(nAbs > nMin)
				break;
			else
				nMin = nAbs;
		}
		return -(i+nCnt*14);
	}
	return 0;
}

void RINGMETHOD(child,SetImgDest)()
{
	RECT rc,rcImage;
	SIZE dest;
	int nOffX=0,nOffY=0;
	
	dest.cx = m_dib.Width();
	dest.cy = m_dib.Height();
	GetClientRect(&rc);
	m_dib.GetDestRect(&rcImage);

	if(m_nRadio >= 0)
	{
		//放大
		dest.cx *= gZoomIn[m_nRadio];
		dest.cy *= gZoomIn[m_nRadio];		
	}
	else if(m_nRadio < 0)
	{
		//缩小
		int nStep = 1,nRadio = -m_nRadio - 1;
		while(nRadio > 13)
		{
			nRadio -= 14;
			nStep *= 100; 
		}
		if(nRadio == 0)
		{
			//66.7%
			dest.cx = (dest.cx*2)/3;
			dest.cy = (dest.cy*2)/3;
		}
		else
		{
			dest.cx /= gZoomOut[nRadio];
			dest.cy /= gZoomOut[nRadio];			
		}
		dest.cx /= nStep;
		dest.cy /= nStep;
	}
	
	rcImage.left += ((rc.right - rc.left)/2 - rcImage.left)*(rcImage.right - rcImage.left -dest.cx)/(rcImage.right - rcImage.left);
	rcImage.right = rcImage.left + dest.cx;
	rcImage.top += ((rc.bottom - rc.top)/2 - rcImage.top)*(rcImage.bottom - rcImage.top -dest.cy)/(rcImage.bottom - rcImage.top);
	rcImage.bottom = rcImage.top + dest.cy;
	
	//调整位置以防超出屏幕范围
	if(rcImage.left > rc.left && rcImage.right > rc.right)
		nOffX = rc.left - rcImage.left;
	else if(rcImage.left < rc.left && rcImage.right < rc.right)
		nOffX = rc.right - rcImage.right;
	if(dest.cx <= (rc.right - rc.left))
		nOffX = ((rc.right - rc.left) - dest.cx)/2 - rcImage.left;
	if(rcImage.top > rc.top && rcImage.bottom > rc.bottom)
		nOffY = rc.top - rcImage.top;
	else if(rcImage.top < rc.top && rcImage.bottom < rc.bottom)
		nOffY = rc.bottom - rcImage.bottom;
	if(dest.cy <= (rc.bottom - rc.top))
		nOffY = ((rc.bottom - rc.top) - dest.cy)/2 - rcImage.top;

	if(dest.cx > (rc.right - rc.left) || dest.cy > (rc.bottom - rc.top))
		SetCursor(m_hCurHand);
	else
		SetCursor(LoadCursor(NULL,IDC_ARROW));

	m_dib.SetDest(rcImage.left+nOffX,rcImage.top+nOffY,dest.cx,dest.cy);
}

//图象超过窗口尺寸,可移动图象(键盘控制)
BOOL RINGMETHOD(child,MoveImg)(int nDir)
{
	RECT rcImg;
	RECT rc;
	BOOL bSet = FALSE;
	int nOffX=0,nOffY=0;
	
	GetClientRect(&rc);
	m_dib.GetDestRect(&rcImg);

	switch(nDir)
	{
	case VK_UP:
		if(rcImg.top < rc.top)
			nOffY = -min(50,rc.top - rcImg.top);
		break;
	case VK_DOWN:
		if(rcImg.bottom > rc.bottom)
			nOffY = min(50,rcImg.bottom - rc.bottom);
		break;
	case VK_LEFT:
		if(rcImg.left < rc.left)
			nOffX = -min(50,rc.left - rcImg.left);
		break;
	case VK_RIGHT:
		if(rcImg.right > rc.right)
			nOffX = min(50,rcImg.right - rc.right);
		break;
	}
	if(nOffX != 0 || nOffY != 0)
	{
		OffsetRect(&rcImg,-nOffX,-nOffY);
		m_dib.SetDest(rcImg.left,rcImg.top,rcImg.right - rcImg.left,rcImg.bottom - rcImg.top);
		return TRUE;
	}
	return FALSE;
}

//图象超过窗口尺寸,可移动图象(鼠标拖动)
void RINGMETHOD(child,MoveImg)(int nOffX,int nOffY)
{
	RECT rcImg;
	RECT rc;
	
	GetClientRect(&rc);
	m_dib.GetDestRect(&rcImg);
	
	if(nOffX < 0)
	{
		if(rcImg.right > rc.right)
			nOffX = -max(nOffX,rc.right - rcImg.right);
		else
			nOffX = 0;
	}
	else
	{
		if(rcImg.left < rc.left)
			nOffX = -min(nOffX,rc.left - rcImg.left);
		else
			nOffX = 0;
	}
	if(nOffY < 0)
	{
		if(rcImg.bottom > rc.bottom)
			nOffY = -max(nOffY,rc.bottom - rcImg.bottom);
		else
			nOffY = 0;
	}
	else
	{
		if(rcImg.top < rc.top)
			nOffY = -min(nOffY,rc.top - rcImg.top);
		else
			nOffY = 0;
	}

	if(nOffX != 0 || nOffY != 0)
	{
		OffsetRect(&rcImg,-nOffX,-nOffY);
		m_dib.SetDest(rcImg.left,rcImg.top,rcImg.right - rcImg.left,rcImg.bottom - rcImg.top);
		m_dib.Draw();
	}
}